﻿using EMall.Application;
using EMall.Query;
using EMall.Uow;
using Microsoft.EntityFrameworkCore;

namespace EMall.IdentityService.Menus
{
    public class MenuAppService : ApplicationService, IMenuAppService
    {
        private readonly IMenuRepository _menuRepository;
        private readonly MenuManager _menuManager;
        public MenuAppService(
            IMenuRepository menuRepository,
            MenuManager menuManager)
        {
            _menuRepository = menuRepository;
            _menuManager = menuManager;
        }
        [UnitOfWork]
        public async Task CreateAsync(CreateMenuDto input)
        {
            var menu = new Menu(
                input.Name,
                await _menuManager.GenerateCodeAsync(input.ParentId),
                input.Type,
                input.ParentId,
                input.Enabled,
                input.Permission,
                input.Route,
                input.Path,
                input.Extensions);
            await _menuRepository.AddAsync(menu);
        }
        [UnitOfWork]
        public async Task UpdateAsync(UpdateMenuDto input)
        {
            var menu = await _menuRepository.GetAsync(input.Id);
            menu.Update(
                input.Name,
                await _menuManager.GenerateNewCodeAsync(menu, input.ParentId),
                input.Type,
                input.ParentId,
                input.Enabled,
                input.Permission,
                input.Route,
                input.Path,
                input.Extensions);
        }
        [UnitOfWork]
        public async Task DeleteAsync(DeleteMenuDto input)
        {
            var product = await _menuRepository.GetAsync(input.Id);
            await _menuRepository.RemoveAsync(product);
        }
        public async Task<MenuDto> GetAsync(int id)
        {
            var menu = await QueryService.GetAsync<Menu, int>(id);
            return Mapper.Map<MenuDto>(menu);
        }
        public async Task<IEnumerable<MenuListDto>> GetListAsync(GetMenuListQueryDto input)
        {
            var permissions = !string.IsNullOrWhiteSpace(input.Permissions) ? input.Permissions.Split(',').ToList() : new List<string>();
            var data = await QueryService.GetQueryable<Menu>()
                .WhereIF(permissions.Any(), o => permissions.Contains(o.Permission))
                .Sorting(input.Sorting)
                .ToListAsync();
            return Mapper.Map<List<Menu>, List<MenuListDto>>(data);
        }
        public async Task<IPagedList<MenuListDto>> GetPagedListAsync(GetMenuListPagingAndSortingQueryDto input)
        {
            var parentIds = !string.IsNullOrWhiteSpace(input.ParentIds) ? input.ParentIds.Split(',').Select(o => Convert.ToInt32(o)) : new List<int>();
            var permissions = !string.IsNullOrWhiteSpace(input.Permissions) ? input.Permissions.Split(',').ToList() : new List<string>();
            var pagedData = await QueryService.GetQueryable<Menu>()
                .WhereIF(parentIds.Any(), o => parentIds.Contains(o.ParentId))
                .WhereIF(permissions.Any(), o => permissions.Contains(o.Permission))
                .Sorting(input.Sorting)
                .ToPagedListAsync(input.PageIndex, input.PageSize);
            return Mapper.Map<Menu, MenuListDto>(pagedData);
        }
        public async Task<MenuTree> GetTreeAsync(GetTreeQueryDto input)
        {
            var permissions = !string.IsNullOrWhiteSpace(input.Permissions) ? input.Permissions.Split(',').ToList() : new List<string>();
            var data = await QueryService.GetQueryable<Menu>()
                .WhereIF(permissions.Any(), o => permissions.Contains(o.Permission) || permissions.Contains(o.Id.ToString()))
                .ToListAsync();
            return TreeBuilder.Build<MenuTree, int>(Mapper.Map<List<Menu>, List<MenuTree>>(data), 0);
        }
    }
}